package com.robinmouren.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.robinmouren.constant.MessageConstant;
import com.robinmouren.constant.NumberConstant;
import com.robinmouren.constant.OrderConstant;
import com.robinmouren.constant.StatusConstant;
import com.robinmouren.dto.*;
import com.robinmouren.entity.*;
import com.robinmouren.exception.InfoIsExistException;
import com.robinmouren.exception.NullOrderInfoException;
import com.robinmouren.exception.NullUserInfoException;
import com.robinmouren.mapper.DriverMapper;
import com.robinmouren.service.IDriverService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.robinmouren.utils.StringUtils;
import com.robinmouren.vo.DriverPageVo;
import com.robinmouren.vo.DriverQuoteVo;
import com.robinmouren.vo.ToBeQuoteVo;
import com.robinmouren.vo.ToGetDriverQuoteVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 司机表，记录司机车辆信息 服务实现类
 * </p>
 *
 * @author Robinmouren
 * @since 2024-05-18
 */
@Service
public class DriverServiceImpl extends ServiceImpl<DriverMapper, Driver> implements IDriverService {


    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private OrderInfoServiceImpl orderService;
    @Autowired
    private QuoteServiceImpl quoteService;
    @Autowired
    private OrderDetailServiceImpl orderDetailService;
    @Autowired
    private RedisTemplate<String,List<OrderStatus>>  redisTemplate;


    /**
     * 司机信息分页查询
     *
     * @param pageDto
     * @return
     */
    @Override
    public Page<DriverPageVo> driverPage(DriverPageDto pageDto) {


        String name = pageDto.getName();
        String plateLicense = pageDto.getPlateLicense();
        int status = pageDto.getStatus();

        Page<Driver> driverPage = new Page<>(pageDto.getPage(), pageDto.getPageSize());

        this.page(driverPage,
                new LambdaQueryWrapper<Driver>()
                        .like(!Objects.equals(plateLicense, ""), Driver::getPlateLicense, plateLicense)
                        .eq(status != -1, Driver::getStatus, status)
        );

        Page<DriverPageVo> page = new Page<>();
        BeanUtils.copyProperties(driverPage, page, "records");

        List<Driver> records = driverPage.getRecords();
        List<DriverPageVo> collect = records.stream().map(item -> {
            DriverPageVo driverPageVo = new DriverPageVo();
            BeanUtils.copyProperties(item, driverPageVo);

            // 从user表中获取姓名
            User user = userService.getById(item.getUserId());
            if (user == null) {
                throw new NullUserInfoException(MessageConstant.USER_NOT_EXIST);
            }
            driverPageVo.setId(item.getUserId().toString());
            driverPageVo.setName(user.getName());
            return driverPageVo;
        }).collect(Collectors.toList());

        // 使用之前未使用的条件分页
        if (!Objects.equals(name, "")) {
            List<DriverPageVo> result = new ArrayList<>();
            collect.forEach(item -> {
                if (item.getName().equals(name)) {
                    result.add(item);
                }
            });
            page.setRecords(result);
            return page;
        }

        page.setRecords(collect);
        return page;
    }


    /**
     * 向司机询价
     *
     * @param dto
     */
    @Override
    public void addQuote(QuoteToDriverDto dto) {

        String orderNumber = dto.getOrderNumber();
        LocalDateTime validEndTime = dto.getValidEndTime();
        OrderInfo orderinfo = orderService.getOne(new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getOrderNumber, orderNumber));
        if (orderinfo == null) {
            throw new NullOrderInfoException(MessageConstant.ORDER_IS_NULL);
        }
        // 获取司机id集合
        List<String> drivers = dto.getDrivers();
        drivers.forEach(item -> {
            Quote quote = Quote.builder()
                    .userId(Long.valueOf(item))
                    .orderId(orderinfo.getId())
                    .unit(dto.getUnit())
                    .validEndTime(validEndTime)
                    .status(StatusConstant.INQUIRY_QUOTATION)
                    .build();
            quoteService.save(quote);
        });

        // 修改订单状态的一步由前端发送到专门修改状态的接口


        // 修改订单表中的询价截至日期
        orderService.update(orderinfo,
                new LambdaUpdateWrapper<OrderInfo>()
                        .set(OrderInfo::getInquiryOverdue, dto.getValidEndTime())
                        .eq(OrderInfo::getOrderNumber, orderNumber)
        );
    }


    /**
     * 司机待报价分页查询
     *
     * @param dto
     * @return
     */
    @Override
    public Page<ToBeQuoteVo> toBePage(QuotationPageDto dto) {

        // 获取dto中的信息
        LocalDateTime startTime = dto.getStartTime();
        LocalDateTime endTime = dto.getEndTime();
        String input = dto.getInput();
        int status = dto.getStatus();
        String id = dto.getId();

        SFunction<OrderInfo, ?> function1 = OrderConstant.ORDER_INPUT_MAP.get(dto.getValue1());
        SFunction<OrderInfo, ?> function2 = OrderConstant.ORDER_INPUT_MAP.get(dto.getValue2());


        // 获取报价表中司机对应的信息
        List<Quote> quoteList = quoteService
                .list(new LambdaQueryWrapper<Quote>()
                        .eq(Quote::getUserId, id));
        // 获取所有订单id
        List<Long> ids = new ArrayList<>();
        quoteList.forEach(item -> {
            ids.add(item.getOrderId());
        });
        if (ids.size() < 1) {
            return null;
        }

        Page<OrderInfo> orderPage = new Page<>(dto.getPage(), dto.getPageSize());
        orderService.page(orderPage,
                new LambdaQueryWrapper<OrderInfo>()
                        .like(!Objects.equals(input, ""), function1, input)
                        .gt(startTime != null, function2, startTime)
                        .lt(endTime != null, function2, endTime)
                        .in(OrderInfo::getId, ids)
                        .eq(status != NumberConstant.ZERO, OrderInfo::getStatus, status)
                        .orderByDesc(OrderInfo::getCreateTime)
        );

        Page<ToBeQuoteVo> page = new Page<>();
        BeanUtils.copyProperties(orderPage, page, "records");

        List<OrderInfo> records = orderPage.getRecords();
        List<ToBeQuoteVo> collect = records.stream().map(item -> {
            ToBeQuoteVo toBeQuoteVo = new ToBeQuoteVo();
            BeanUtils.copyProperties(item, toBeQuoteVo);

            List<OrderDetail> list = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                    .eq(OrderDetail::getOrderId, item.getId()));
            if (list.size() < 1) {
                throw new NullOrderInfoException(MessageConstant.ORDER_IS_NULL);
            }
            // 获取货物信息中的名称
            toBeQuoteVo.setName(StringUtils.fetchNameInList(list));
            // 获取询价截止时间
            toBeQuoteVo.setValidEndTime(item.getInquiryOverdue());
            // 分割始发地和目的地
            toBeQuoteVo.setOriginPlace(StringUtils.partitionStringToGetFirst(item.getOriginPlace()));
            toBeQuoteVo.setDestination(StringUtils.partitionStringToGetFirst(item.getDestination()));
            return toBeQuoteVo;
        }).collect(Collectors.toList());

        page.setRecords(collect);
        return page;
    }


    /**
     * 司机报价
     *
     * @param dto
     */
    @Override
    public void driverQuote(DriverQuoteDto dto) {

        // 获得订单号
        OrderInfo info = orderService.getOne(new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getOrderNumber, dto.getOrderNumber()));
        if(info == null){
            throw new NullOrderInfoException(MessageConstant.ORDER_IS_NULL);
        }
        String orderNumber = info.getOrderNumber();

        Quote quote = dto.getQuote();
        quote.setStatus(StatusConstant.QUOTED);
        quoteService.update(quote,
                new LambdaUpdateWrapper<Quote>()
                        .eq(Quote::getOrderId,info.getId())
                        .and(wrapper -> {wrapper.eq(Quote::getUserId,dto.getId());}));

        // 修改订单状态
        info.setStatus(StatusConstant.QUOTED);
        info.setQuotationOverdue(quote.getValidEndTime());
        orderService.updateById(info);

    }


    /**
     * 承运商获取运输询价
     * @param orderNumber
     * @return
     */
    @Override
    public ToGetDriverQuoteVo toGetDriverQuote(String orderNumber) {

        // 获取订单信息
        OrderInfo orderinfo = orderService.getOne(new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getOrderNumber, orderNumber));
        if(orderinfo == null){
            throw new NullOrderInfoException(MessageConstant.ORDER_IS_NULL);
        }

        Long orderId = orderinfo.getId();
        String getOriginFirst = StringUtils.partitionStringToGetFirst(orderinfo.getOriginPlace());
        String getDesFirst = StringUtils.partitionStringToGetFirst(orderinfo.getDestination());
        LocalDateTime inquiryOverdue = orderinfo.getInquiryOverdue();

        // 获取司机报价信息
        List<Quote> quotes = quoteService.list(new LambdaQueryWrapper<Quote>()
                .eq(Quote::getOrderId, orderId)
                .and(wrapper -> {
                    wrapper.eq(Quote::getStatus,StatusConstant.QUOTED);}));

        List<DriverQuoteVo> collect = quotes.stream().map(item -> {
            DriverQuoteVo driverQuoteVo = new DriverQuoteVo();
            BeanUtils.copyProperties(item, driverQuoteVo);

            driverQuoteVo.setOrigin(getOriginFirst);
            driverQuoteVo.setDestination(getDesFirst);
            driverQuoteVo.setUnit(item.getUnit());
            driverQuoteVo.setUnitFee(item.getFee() + item.getUnit());

            Driver driver = this.getOne(new LambdaQueryWrapper<Driver>()
                    .eq(Driver::getUserId, item.getUserId()));
            if (driver == null) {
                throw new NullUserInfoException(MessageConstant.USER_NOT_EXIST);
            }
            BeanUtils.copyProperties(driver, driverQuoteVo);

            User user = userService.getById(item.getUserId());
            if (user == null) {
                throw new NullUserInfoException(MessageConstant.USER_NOT_EXIST);
            }
            driverQuoteVo.setName(user.getName());

            driverQuoteVo.setId(item.getId().toString());
            return driverQuoteVo;
        }).collect(Collectors.toList());

        return ToGetDriverQuoteVo.builder()
                .origin(getOriginFirst)
                .destination(getDesFirst)
                .unit(collect.get(0).getUnit())
                .validEndTime(inquiryOverdue)
                .list(collect)
                .build();
    }


    /**
     * 承运商报价
     * @param dto
     */
    @Override
    public void carriersQuote(CarriersQuoteDto dto) {

        String userId = dto.getUserId();
        String quoteId = dto.getQuoteId();
        String orderNumber = dto.getOrderNumber();
        Quote dtoQuote = dto.getQuote();
        LocalDateTime validEndTime = dtoQuote.getValidEndTime();
        Quote quote = new Quote();
        quote.setStatus(StatusConstant.QUOTED_CARRIERS);

        // 判断报价是否存在
        Quote one = quoteService.getOne(
                new LambdaQueryWrapper<Quote>()
                        .eq(Quote::getId, quoteId)
                        .and(wrapper -> {
                            wrapper.eq(Quote::getStatus, StatusConstant.QUOTED_CARRIERS);}));
        if(one != null){throw new InfoIsExistException(MessageConstant.QUOTE_IS_EXIST);}

        // 获取订单信息
        OrderInfo orderInfo = orderService.getOne(new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getOrderNumber, orderNumber));
        orderInfo.setStatus(StatusConstant.QUOTED_CARRIERS);
        if(validEndTime == null && !Objects.equals(quoteId, "1")){
            // 若承运商未填写报价，则使用司机报价，将对应司机报价信息状态修改
            quoteService.update(quote,
                    new LambdaUpdateWrapper<Quote>()
                            .eq(Quote::getId,quoteId));
        }else if(validEndTime != null){
            orderInfo.setQuotationOverdue(validEndTime);
            // 若承运商填写报价，则使用承运商报价
            BeanUtils.copyProperties(dtoQuote,quote);
            // 设置用户id
            quote.setUserId(Long.valueOf(userId));
            // 获取订单id
            quote.setOrderId(orderInfo.getId());
            // 修改状态
            quote.setStatus(StatusConstant.QUOTED_CARRIERS);
            // 保存
            quoteService.save(quote);
        }
        // 修改订单信息
        orderService.updateById(orderInfo);

        // 修改订单状态map中的信息
        // 将缓存中订单的状态信息修改
        List<OrderStatus> list = redisTemplate.opsForValue().get(orderNumber);
        // 订单信息为空
        if (list == null) {throw new NullOrderInfoException(MessageConstant.ORDER_IS_NULL);}
        OrderStatus.reviseList(list, StatusConstant.QUOTED_CARRIERS, LocalDateTime.now());
        // 重新将值存入
        redisTemplate.opsForValue().set(orderNumber, list);
    }
}
